/***************************************************************************
 *   Copyright (C) 2009 by maarten,,,   *
 *   maarten@maarten-laptop   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef DRAWRAYTRACER_H
#define DRAWRAYTRACER_H

#include <QVector>
#include <QColor>

#include "cgpanel/raytracer/raymatrix.h"

// defines the maximum recursive level
#define MAX_REC_LEVEL 5

namespace object{
    class Vertex;
    class Plane;
};

namespace scene{
    class Camera;
    class Shape;
    class SceneManager;
    class Camera;
    class PointLight;
    class Texture;
    class Material;
};

namespace draw {

class Ray;
class FloatMatrix;
class BVHTree;
class HitRecord;


/**
	@author maarten,,, <maarten@maarten-laptop>
*/
class RayTracer{
public:
    RayTracer(int w, int h, int tempAA);
    ~RayTracer();
    void initViewRays(scene::Camera *cam);
    void setShapes(QVector<object::Plane*> &shapesToDraw,
                                            scene::SceneManager *sceneMgr );
    //bool intersect(int x, int y);
    //bool intersectBVH(int x, int y);
    bool rayColor(Ray * ray);
    inline const QColor& getPenColor(){return *(m_recursiveColors[0]);}
    
    inline Ray * getRay(int x, int y){return m_rayMatrix->getRay(x,y);}
    
    inline void setBgcolor(float r, float g, float b){rBG = r; gBG = g; bBG =
b;}
    inline int getAntialiasing(){return antialiasing;}
    
    void initViewSubFase(int x, int y, int p, int q);
private:
    RayMatrix * m_rayMatrix; // rays
    
    float rBG;
    float gBG;
    float bBG;
    
    FloatMatrix *aMat; // 4X4 matrix for faster barycentric calc
    object::Vertex *bMat; // 3X1 matrix for faster barycentric calc

    float m_width, m_height;
    
    QColor m_drawColor;
    QVector<QColor*> m_recursiveColors; //max recursive level = 10
    int rec_level;
   
    QVector<object::Plane*> m_planesToDraw;
    scene::SceneManager * m_sceneMgr;
    
    float lastAlpha;
    float lastBeta;
    float lastGamma;
    
    int materialType; // 0 = diffuse, 1 = phong, 2 = more!
    bool isPhong;
    bool isDiffuse;
    scene::Material *mainMaterial;
    scene::Material *phongMaterial;
    scene::Material *diffuseMaterial;
    
    int shininess; // when phong
    
    bool m_reflect;
    bool m_refract;
    object::Vertex * m_specColor;
    
    scene::Camera * m_cam;
   
    // calculates color
    void calcColor(/*float matx, float maty, float matz*/);
    
    // calculates texture color
    void calcTexColor(object::Plane * plane);
    
    // shadow funtion
    bool isShadow(object::Vertex *start, object::Vertex *end);
    
    // returns ray
    object::Vertex* getRayDirection(int i, int j);
    object::Vertex* getRayDirection(int i, int j, int p, int q);
    
    // acceleration structure
    BVHTree *bvhTree;
    HitRecord * m_hitRecord;
    HitRecord * fake;
    
    // helpvars for raytracing
    QVector<object::Vertex *> m_realPosXYZ;
    //object::Vertex * realPosXYZ;
    object::Vertex * surfNorm;
    object::Vertex * scaledV;
    object::Vertex * color;
    
    // color help vars
    object::Vertex * lightDir;
    object::Vertex * lightPos;
    object::Vertex * hVec;
    QVector<scene::PointLight *> pLights;
    
    //antialiasing N
    int antialiasing;
    
    // refraction
    bool refract(object::Vertex *d, object::Vertex * norm, 
                 float nt, object::Vertex ** t);
                 
    Ray * shadowRay;
    
     // initviewrays
    draw::FloatMatrix * m_s1;
    draw::FloatMatrix * m_s2;
    
    bool m_glossy;
    float m_glossyFactor;
    
};

}

#endif
